﻿/*
 * TsCaster.cpp
 *
 *  Created on: 2016年8月24日
 *      Author: zhengboyuan
 */

#include "BasicType.h"
#include "TsCaster.h"
#include "TsApplication.h"
#include "UdpTsMediaCaster.h"
#include "RtpTsMediaCaster.h"

#include "TcpTsMediaCaster.h"
#include "HttpTsMediaCaster.h"

#include "CLog.h"
#include "MFormatUtil.h"
#include "AppConst.h"
#include "MediaCasterConfig.h"


static TsApplication& app()
{
	return TsApplication::instance();
}




/**
 * 初始化
 * @return 0 表示成功
 */
DLLEXPORT int tscaster_init()
{
	app().init();

	return 0;
}

/**
 * 反初始化
 * @return
 */
DLLEXPORT int tscaster_quit()
{
	app().quit();

	return 0;
}


/**
 * 打开发送通道
 * @param handle	句柄
 * @param protocol	传输协议, 暂支持UDP
 * @param outPort	本地端口
 * @param fmt		媒体格式
 * @return 0 表示成功
 */
DLLEXPORT int tscaster_open(tscaster_t* handle, int protocol, int outPort, const MFormat* fmt)
{
	CLog::debug("tscaster_open protocol:%d, port:%d\n", protocol, outPort);

	if (!handle)
	{
		return EINVAL;
	}

	TsMediaCasterPtr caster;
	if (protocol == TSCASTER_PROTOCOL_UDP)
	{
		caster.reset(new av::UdpTsMediaCaster());
	}
	else if (protocol == TSCASTER_PROTOCOL_RTP)
	{
		caster.reset(new av::RtpTsMediaCaster());
	}
    else if (protocol == TSCASTER_PROTOCOL_TCP)
    {
        caster.reset(new av::TcpTsMediaCaster());
    }
    else if (protocol == TSCASTER_PROTOCOL_HTTP)
    {
        caster.reset(new av::HttpTsMediaCaster());
    }
	else 
	{
		caster.reset(new av::UdpTsMediaCaster());
	}
	
	av::MediaFormat mfmt;
	av::MFormatUtil::copyTo(fmt, mfmt);

	int ret = caster->open("", outPort, mfmt);
	if (ret != 0)
	{
		return ret;
	}

	*handle = app().put(caster);

	caster->setID(*handle);

	return 0;
}

/**
 * 关闭通道
 * @param handle 通道句柄
 */
DLLEXPORT void tscaster_close(tscaster_t handle)
{
	TsMediaCasterPtr caster = app().remove(handle);
	if (caster)
	{
		caster->close();
	}
}


/**
 * 添加发送目标
 * @param handle 通道句柄
 * @param ip		地址
 * @param port		端口
 * @return	0 表示成功
 */
DLLEXPORT int tscaster_add_target(tscaster_t handle, const char* ip, int port)
{
	if ((ip == NULL) || (strlen(ip) == 0))
	{
		return EINVAL;
	}

	TsMediaCasterPtr caster = app().get(handle);
	if (!caster)
	{
		return ENOENT;
	}

	bool done = caster->addTarget(ip, port);

	return done ? 0 : EACCES;
}

/**
 * 删除发送目标
 * @param handle	通道
 * @param ip		地址
 * @param port	端口
 * @return 0 表示成功
 */
DLLEXPORT int tscaster_remove_target(tscaster_t handle, const char* ip, int port)
{
	if ((ip == NULL) || (strlen(ip) == 0))
	{
		return EINVAL;
	}

	TsMediaCasterPtr caster = app().get(handle);
	if (!caster)
	{
		return ENOENT;
	}

	caster->removeTarget(ip, port);

	return 0;
}


/**
 * 删除所有的发送目标
 * @param handle
 * @return
 */
DLLEXPORT int tscaster_remove_all_target(tscaster_t handle)
{
	TsMediaCasterPtr caster = app().get(handle);
	if (!caster)
	{
		return ENOENT;
	}

	caster->removeAllTarget();
	return 0;
}


DLLEXPORT int tscaster_write(tscaster_t handle, const MPacket* packet)
{
	if (!packet || !packet->data)
	{
		return EINVAL;
	}

	TsMediaCasterPtr caster = app().get(handle);
	if (!caster)
	{
		return ENOENT;
	}

	caster->write(packet->type, packet->data, packet->size, packet->pts, packet->duration, packet->flags);

	return 0;
}


/**
 * 设置缓冲区最大时长, 单位为毫秒
 * @param ms
 */
DLLEXPORT void tscaster_setQueueDuration(int ms)
{
    av::MediaCasterConfig::QUEUE_DURATION = ms;
}

/**
 * 设置socket发送缓冲区大小
 * @param size
 */
DLLEXPORT void tscaster_setSendBufSize(int size)
{
	if (size > 0)
	{
	    av::MediaCasterConfig::SEND_BUFFER_SIZE = size;
	}
}

DLLEXPORT void tscaster_set_stack_size(int stackSize)
{
    if (stackSize < 0)
    {
        return;
    }

    AppConst::THREAD_STACK_SIZE = stackSize;
}
